package com.bxd.baodan.base;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;

import com.google.gson.Gson;
import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.handmark.pulltorefresh.library.PullToRefreshListView;
import com.bxd.baodan.App;
import com.bxd.baodan.R;
import com.bxd.baodan.adapter.CommonAdapter;
import com.bxd.baodan.adapter.ViewHolder;
import com.bxd.baodan.app.LoginInfo;
import com.bxd.baodan.fragment.BaseFragment;
import com.bxd.baodan.util.JSONUtil;
import com.bxd.baodan.util.LogUtil;
import com.bxd.baodan.util.NetUtil;
import com.bxd.baodan.util.StringUtil;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

/**
 * 下拉刷新,上拉加载更多的fragment
 *
 * @author oldfeel
 *         <p>
 *         Created on: 2014年3月2日
 */
public abstract class BaseListFragment<T> extends BaseFragment implements View.OnClickListener {
    protected PullToRefreshListView refView;
    protected int page = 0;

    public NetUtil getNetUtil() {
        return netUtil;
    }

    public void setNetUtil(NetUtil netUtil) {
        this.netUtil = netUtil;
    }

    protected NetUtil netUtil;
    protected CommonAdapter adapter;
    protected boolean canLoadMore = true;
    public static final int OFFSET = 10;


    public PullToRefreshBase.Mode mMode;

    protected List<T> mData = new ArrayList<>();
    //防止data是类类型的,需要进一步确定数组对应的字段
    protected ListView listView;
    protected View footer;
    protected View view;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        view = inflater.inflate(getFragmentLayout(), container, false);
        refView = (PullToRefreshListView) view.findViewById(R.id.pull_refresh_list);


        footer = View.inflate(getActivity(), R.layout.list_null_footer, null);
        listView = refView.getRefreshableView();
        page = 1;
        addHeadView();

        adapter = new CommonAdapter<T>(getActivity(), mData, getItemLayout()) {
            @Override
            public void convert(ViewHolder holder, T item) {
                BaseListFragment.this.convert(holder, item);
            }
        };
        initRefresh();
        refView.setAdapter(adapter);
        preDone(view);
        // TODO: 2017/7/7 可能有坑
        try {
            setUsualNetUtil();
        } catch (Exception e) {
            LogUtil.e("setUsualNetUtil: " + e.getMessage());
        }
        return view;
    }

    protected void addHeadView() {
    }


    protected void initRefresh() {
        refView.setMode(mMode == null ? PullToRefreshBase.Mode.BOTH : mMode);
        refView.setOnRefreshListener(new PullToRefreshBase.OnRefreshListener2<ListView>() {
            @Override
            public void onPullDownToRefresh(PullToRefreshBase<ListView> refreshView) {
                page = 1;
                canLoadMore = true;
                getData();
            }

            @Override
            public void onPullUpToRefresh(PullToRefreshBase<ListView> refreshView) {

                if (canLoadMore) {
                    page++;
                    getData();
                } else {
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            getActivity().runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    refView.onRefreshComplete();
                                }
                            });
                        }
                    }).start();
                }
            }
        });
    }


    protected void getData() {


        if (netUtil == null) {
            setUsualNetUtil();
        }
        setNetParams();
        initData();
    }

    private void initData() {
        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {

                String jsonStr = netUtil./*okPost()*/postStringResult();
                LogUtil.e("data: " + jsonStr);
                //   jsonStr = " {\"code\":0,\"tips\":\"\",\"data\":[]}";
                parseJsonStr(jsonStr);
                if (JSONUtil.isSuccess(jsonStr)) {
                    e.onNext(jsonStr);
                } else {
                    LogUtil.e("errorCode: " + JSONUtil.getCode(jsonStr));
                    final String msg = JSONUtil.getMessage(jsonStr);

                    getActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            if (!StringUtil.isEmpty(msg)) {
                                showToast(msg);
                            }
                        }
                    });

                }
                e.onComplete();
            }
        }).map(new Function<String, List<T>>() {
            @Override
            public List<T> apply(String s) throws Exception {
                final String json_data = JSONUtil.getData(s);

                if (json_data.startsWith("[")) {
                    return new Gson().fromJson(json_data, getTypeToken());
                } else if (json_data.startsWith("{")) {

                    String arrayStr = getArrayStr(json_data);
                    if (arrayStr.equals("list")) {
                        String list = JSONUtil.getArrayData("list", json_data);
                        return new Gson().fromJson(list, getTypeToken());
                    }

                    if (arrayStr != null) {
                        LogUtil.e("---array---not ---list");
                        return new Gson().fromJson(arrayStr, getTypeToken());
                    }
                    LogUtil.e("------未设置getArrayStr: ");
                    return null;
                } else {
                    LogUtil.e("data类型不对: ");
                    return null; // FIXME: 2017/6/23 需要测试没有数组的接口
                }
            }
        }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())  //回到主线程去处理请求结果
                .subscribe(new Observer<List<T>>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(List<T> list) {
                        if (page == 1) {
                            mData.clear();
                            setNullPage(list.size() == 0);//首次加载数据是否为空
                        }
                        if (list.size() < OFFSET) {
                            canLoadMore = false;
                        }
                        mData.addAll(list);
                        adapter.notifyDataSetChanged();
                    }

                    @Override
                    public void onError(Throwable e) {
                        // FIXME: 2017/6/20 如何处理异常
                    }

                    @Override
                    public void onComplete() {
                        refView.onRefreshComplete();
                        if (netUtil.pd != null) {
                            netUtil.pd.cancel();
                        }
                    }
                });
    }

    protected void setNetParams() {
        netUtil.showPd("");
        netUtil.setParams("page", page);
        netUtil.setParams("offset", page);
        try {
            netUtil.setParams("uid",
                    LoginInfo.getInstance(App.getContext())
                            .getUser().getU_id());
            netUtil.setParams("pwd",
                    LoginInfo.getInstance(App.getContext())
                            .getUser().getPwd());
        } catch (Exception e) {
        }
    }

    /**
     * 空实现,其他操作
     *
     * @param v 布局view
     */
    protected abstract void preDone(View v);

    /**
     * @return fragment的布局, 应该包含pulltorefresh_layout
     */
    protected abstract int getFragmentLayout();


    /**
     * @return 返回子类中实际要转换的List<Bean>T
     * return new TypeToken<List<T>>() {}.getType();
     */
    protected abstract Type getTypeToken();


    /**
     * 设置常用的网络,
     * 如果new fragment时就setNetUtil()过,不会起作用
     * 方便对象初始化,不用经常找网络
     */

    protected abstract void setUsualNetUtil();


    /**
     * @return item的布局文件
     */
    protected abstract int getItemLayout();

    /**
     * item的布局的交互
     */
    protected abstract void convert(ViewHolder holder, T item);


    /**
     * 得到json中data中的数组string
     *
     * @param json_data data:{}
     * @return []
     */
    protected abstract String getArrayStr(String json_data);


    /**
     * 设置上拉下拉类型
     */
    protected void setMode() {

    }


    /**
     * 处理json中data对应数据,data是{},处理其中的字段
     *
     * @param jsonStr data字段对应数据
     */
    protected void parseJsonStr(String jsonStr) {
    }


    @Override
    public void onClick(View v) {

    }

    /**
     * 设置空页面
     */
    protected void setNullPage(boolean isNullPage) {
        if (!isNullPage) {
            try {
                listView.removeFooterView(footer);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        if (isNullPage && listView.getFooterViewsCount() == 1) {
            listView.addFooterView(footer);
        }
    }

    /**
     * 自动刷新
     */
    protected void autoRefresh() {
        refView.setMode(PullToRefreshBase.Mode.PULL_FROM_START);
        refView.setRefreshing();
        refView.setMode(mMode == null ? PullToRefreshBase.Mode.BOTH : mMode);
    }


    public void refreshStyle() {

    }
}
